home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / advanced97 / SPHERE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  4.6 KB  |  186 lines

  1. #include <stdlib.h>
  2. #include <GL/glut.h>
  3. #include <math.h>
  4.  
  5. #ifndef __sgi
  6. /* Most math.h's do not define float versions of the math functions. */
  7. #define sqrtf(x) ((float)sqrt((x)))
  8. #endif
  9.  
  10. /* sphere tessellation code based on code originally
  11.  * written by Jon Leech (leech@cs.unc.edu) 3/24/89
  12.  */
  13.  
  14. typedef struct {
  15.     float x, y, z;
  16. } point;
  17.  
  18. typedef struct {
  19.     point pt[3];
  20. } triangle;
  21.  
  22. /* six equidistant points lying on the unit sphere */
  23. #define XPLUS {  1,  0,  0 }    /*  X */
  24. #define XMIN  { -1,  0,  0 }    /* -X */
  25. #define YPLUS {  0,  1,  0 }    /*  Y */
  26. #define YMIN  {  0, -1,  0 }    /* -Y */
  27. #define ZPLUS {  0,  0,  1 }    /*  Z */
  28. #define ZMIN  {  0,  0, -1 }    /* -Z */
  29.  
  30. /* for icosahedron */
  31. #define CZ (0.866025403)    /*  cos(30) */
  32. #define SZ (0.5)        /*  sin(30) */
  33. #define C1 (0.951056516)    /* cos(18),  */
  34. #define S1 (0.309016994)    /* sin(18) */
  35. #define C2 (0.587785252)    /* cos(54),  */
  36. #define S2 (0.809016994)    /* sin(54) */
  37. #define X1 (C1*CZ)
  38. #define Y1 (S1*CZ)
  39. #define X2 (C2*CZ)
  40. #define Y2 (S2*CZ)
  41.  
  42. #define Ip0     {0.,     0.,     1.}
  43. #define Ip1    {-X2,     -Y2,     SZ}
  44. #define Ip2    {X2,     -Y2,     SZ}
  45. #define Ip3    {X1,     Y1,     SZ}
  46. #define Ip4    {0,     CZ,     SZ}
  47. #define Ip5    {-X1,     Y1,     SZ}
  48.  
  49. #define Im0    {-X1,     -Y1,     -SZ}
  50. #define Im1    {0,     -CZ,     -SZ}
  51. #define Im2    {X1,     -Y1,     -SZ}
  52. #define Im3    {X2,     Y2,     -SZ}
  53. #define Im4    {-X2,     Y2,     -SZ}
  54. #define Im5    {0.,     0.,     -1.}
  55.  
  56. /* vertices of a unit icosahedron */
  57. static triangle icosahedron[20]= {
  58.     /* front pole */
  59.     { {Ip0, Ip1, Ip2}, },
  60.     { {Ip0, Ip5, Ip1}, },
  61.     { {Ip0, Ip4, Ip5}, },
  62.     { {Ip0, Ip3, Ip4}, },
  63.     { {Ip0, Ip2, Ip3}, },
  64.  
  65.     /* mid */
  66.     { {Ip1, Im0, Im1}, },
  67.     { {Im0, Ip1, Ip5}, },
  68.     { {Ip5, Im4, Im0}, },
  69.     { {Im4, Ip5, Ip4}, },
  70.     { {Ip4, Im3, Im4}, },
  71.     { {Im3, Ip4, Ip3}, },
  72.     { {Ip3, Im2, Im3}, },
  73.     { {Im2, Ip3, Ip2}, },
  74.     { {Ip2, Im1, Im2}, },
  75.     { {Im1, Ip2, Ip1}, },
  76.  
  77.     /* back pole */
  78.     { {Im3, Im2, Im5}, },
  79.     { {Im4, Im3, Im5}, },
  80.     { {Im0, Im4, Im5}, },
  81.     { {Im1, Im0, Im5}, },
  82.     { {Im2, Im1, Im5}, },
  83. };
  84.  
  85. /* normalize point r */
  86. static void
  87. normalize(point *r) {
  88.     float mag;
  89.  
  90.     mag = r->x * r->x + r->y * r->y + r->z * r->z;
  91.     if (mag != 0.0f) {
  92.     mag = 1.0f / sqrtf(mag);
  93.     r->x *= mag;
  94.     r->y *= mag;
  95.     r->z *= mag;
  96.     }
  97. }
  98.  
  99. /* linearly interpolate between a & b, by fraction f */
  100. static void
  101. lerp(point *a, point *b, float f, point *r) {
  102.     r->x = a->x + f*(b->x-a->x);
  103.     r->y = a->y + f*(b->y-a->y);
  104.     r->z = a->z + f*(b->z-a->z);
  105. }
  106.  
  107. void
  108. sphere(int maxlevel) {
  109.     int nrows = 1 << maxlevel;
  110.     int s;
  111.  
  112.     /* iterate over the 20 sides of the icosahedron */
  113.     for(s = 0; s < 20; s++) {
  114.     int i;
  115.     triangle *t = &icosahedron[s];
  116.     for(i = 0; i < nrows; i++) {
  117.         /* create a tstrip for each row */
  118.         /* number of triangles in this row is number in previous +2 */
  119.         /* strip the ith trapezoid block */
  120.         point v0, v1, v2, v3, va, vb;
  121.         int j;
  122.         lerp(&t->pt[1], &t->pt[0], (float)(i+1)/nrows, &v0);
  123.         lerp(&t->pt[1], &t->pt[0], (float)i/nrows, &v1);
  124.         lerp(&t->pt[1], &t->pt[2], (float)(i+1)/nrows, &v2);
  125.         lerp(&t->pt[1], &t->pt[2], (float)i/nrows, &v3);
  126.         glBegin(GL_TRIANGLE_STRIP);
  127. #define V(v)    { point x; x = v; normalize(&x); glNormal3fv(&x.x); glVertex3fv(&x.x); }
  128.         V(v0);
  129.         V(v1);
  130.         for(j = 0; j < i; j++) {
  131.         /* calculate 2 more vertices at a time */
  132.         lerp(&v0, &v2, (float)(j+1)/(i+1), &va);
  133.         lerp(&v1, &v3, (float)(j+1)/i, &vb);
  134.         V(va);
  135.         V(vb);
  136.         }
  137.         V(v2);
  138. #undef V
  139.         glEnd();
  140.     }
  141.     }
  142. }
  143.  
  144. float *
  145. sphere_tris(int maxlevel) {
  146.     int nrows = 1 << maxlevel;
  147.     int s, n;
  148.     float *buf, *b;
  149.  
  150.     n = 20*(1 << (maxlevel * 2));
  151.     b = buf = (float *)malloc(n*3*3*sizeof(float));
  152.  
  153.     /* iterate over the 20 sides of the icosahedron */
  154.     for(s = 0; s < 20; s++) {
  155.     int i;
  156.     triangle *t = &icosahedron[s];
  157.     for(i = 0; i < nrows; i++) {
  158.         /* create a tstrip for each row */
  159.         /* number of triangles in this row is number in previous +2 */
  160.         /* strip the ith trapezoid block */
  161.         point v0, v1, v2, v3, va, vb, x1, x2;
  162.         int j;
  163.         lerp(&t->pt[1], &t->pt[0], (float)(i+1)/nrows, &v0);
  164.         lerp(&t->pt[1], &t->pt[0], (float)i/nrows, &v1);
  165.         lerp(&t->pt[1], &t->pt[2], (float)(i+1)/nrows, &v2);
  166.         lerp(&t->pt[1], &t->pt[2], (float)i/nrows, &v3);
  167. #define V(a, c, v)    { point x = v; normalize(&a); normalize(&c); normalize(&x); \
  168.             b[0] = a.x; b[1] = a.y; b[2] = a.z; \
  169.             b[3] = c.x; b[4] = c.y; b[5] = c.z; \
  170.             b[6] = x.x; b[7] = x.y; b[8] = x.z; b+=9; }
  171.         x1 = v0;
  172.         x2 = v1;
  173.         for(j = 0; j < i; j++) {
  174.         /* calculate 2 more vertices at a time */
  175.         lerp(&v0, &v2, (float)(j+1)/(i+1), &va);
  176.         lerp(&v1, &v3, (float)(j+1)/i, &vb);
  177.         V(x1,x2,va); x1 = x2; x2 = va;
  178.         V(vb,x2,x1); x1 = x2; x2 = vb;
  179.         }
  180.         V(x1, x2, v2);
  181. #undef V
  182.     }
  183.     }
  184.     return buf;
  185. }
  186.